package pl.enigmatic.math.perm;

import java.util.List;

import pl.enigmatic.ValueConverter;
import pl.enigmatic.math.BijectionSequence;
import pl.enigmatic.util.Alphabet;
import pl.enigmatic.util.Arrays;
import pl.enigmatic.util.Strings;


public class LatinsPermutation extends SymbolsPermutation<Character> {

	private static final long serialVersionUID = 1L;

	private static final BijectionSequence<Character> LATIN = new BijectionSequence<Character>(Arrays.convert(Alphabet.abcLU));

	public static final int LETTERS_NUM = Alphabet.LETTERS_NUM;
	public static final String ID = Alphabet.abcSU;

	static {
		LATIN.setRightConverter(new ValueConverter<Character, Character>() {

			@Override
			public Character convert(final Character value) {
				return Character.toUpperCase(value);
			}

			@Override
			public Character convertBack(final Character value) {
				return value;
			}
		});
	}

	public static LatinsPermutation parseString(final String string) {
		if (string.length() == LETTERS_NUM) {
			final boolean[] tmp = Arrays.constant(LETTERS_NUM, false);
			final int tab[] = Arrays.identity(LETTERS_NUM);
			for (int i = 0; i < LETTERS_NUM; i++) {
				tab[i] = Alphabet.number(string.charAt(i));
				if (tmp[tab[i]]) { return null; }
				tmp[tab[i]] = true;
			}
			final LatinsPermutation res = new LatinsPermutation();
			if (res.set(tab)) { return res; }
		}
		return null;
	}

	public static LatinsPermutation fromArray(final int[] array) {
		if (array.length == LETTERS_NUM) {
			final LatinsPermutation res = new LatinsPermutation();
			if (res.set(array)) { return res; }
		}
		return null;
	}

	public LatinsPermutation() {
		super(LATIN);
	}

	public String encipher(final String plaintext) {
		final List<Character> list = encipher(Arrays.convert(Strings.getChars(plaintext)));
		String res = "";
		for (final Character c : list) {
			res += c;
		}
		return res;
	}

	/**
	 * tworzy permutację z odpowiedniego ciągu liter str - muszﾹ to by￦ litery A-Z gdy podany jest zﾳy parametr wejﾜciowy - rzuca wyjﾹtek
	 */
	public boolean fromStr(final String str) {
		if (str.length() == length()) {
			final boolean[] tmp = Arrays.constant(length(), false);
			final int tab[] = Arrays.identity(length());
			for (int i = 0; i < length(); i++) {
				tab[i] = Alphabet.number(str.charAt(i));
				if (tmp[tab[i]]) { return false; }
				tmp[tab[i]] = true;
			}
			return set(tab);
		}
		return false;
	}

	/**
	 * Tries to clone <code>this</code> object instance.
	 * @see java.lang.Object#clone()
	 */
	@Override
	public LatinsPermutation clone() {
		LatinsPermutation res = new LatinsPermutation();
		res.set(array());
		return res;
	}

}
